﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bluyel.Core;
using Bluyel.Core.Tests.IntegTests;

namespace DevApp
{
    class Program
    {
        //---------------------------------------------------------------------
        static void CreateBasicType()
        {
            BluyelCore core = new BluyelCore();

            //--configure the TypeSystem, define availables types 
            // create basics types
            IType typeInt = core.TypeBuilder.DefineTypeInt();

            IType typeDouble = core.TypeBuilder.DefineTypeDouble();
            IType typeString = core.TypeBuilder.DefineTypeString();
            IType typeBool = core.TypeBuilder.DefineTypeBool();

            // find type by name, by id
            IType typeIntFind= core.TypeFinder.FindTypeByName("int");
            IType typeIntFindName = core.TypeFinder.FindTypeByName(TypeDef.TypeIntName);
            IType typeIntFindId = core.TypeFinder.FindTypeById(TypeDef.TypeIntId);

            bool res = core.TypeFinder.IsTypeBool(typeBool);
            res = core.TypeFinder.IsTypeString(typeBool);

        }

        //---------------------------------------------------------------------
        // Try to add 2 times a same type: by the name, by the id
        // TODO: must failed

        //---------------------------------------------------------------------
        // Create basic type, rename built-in type, exp: Integer, String Boolean,..
        static void CreateBasicTypeSetName()
        {
            BluyelCore core = new BluyelCore();

            IType typeInt = core.TypeBuilder.DefineTypeInt("Integer");

            // find type by name, by id
            IType typeIntFind = core.TypeFinder.FindTypeByName("Integer");
            IType typeIntFindName = core.TypeFinder.FindTypeByName(TypeDef.TypeIntName);
            IType typeIntFindId = core.TypeFinder.FindTypeById(TypeDef.TypeIntId);
        }

        //---------------------------------------------------------------------
        // Create basic type, create a listType, push type
        static void CreateBasicTypePutInListType()
        {
            BluyelCore core = new BluyelCore();

            IType typeInt = core.TypeBuilder.DefineTypeInt();
            IType typeDouble = core.TypeBuilder.DefineTypeDouble();
            IType typeString = core.TypeBuilder.DefineTypeString();
            IType typeBool = core.TypeBuilder.DefineTypeBool();

            // group type by theme
            ListType listTypeVar = core.TypeBuilder.CreateListType(TypeDef.ListTypeVarName);
            listTypeVar.Add(typeInt);
            listTypeVar.Add(typeDouble);
            listTypeVar.Add(typeString);
            listTypeVar.Add(typeBool);

            // find types in this list
            IType typeIntFind= listTypeVar.FindTypeByName("int");
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create types and some data value, based on these types.
        /// </summary>
        static void CreateDValBasicType()
        {
            BluyelCore core = new BluyelCore();
            IType typeInt = core.TypeBuilder.DefineTypeInt();
            IType typeDouble = core.TypeBuilder.DefineTypeDouble();
            IType typeString = core.TypeBuilder.DefineTypeString();
            IType typeBool = core.TypeBuilder.DefineTypeBool();

            //--create some data value, based on type
            IValue dv = core.DataBuilder.CreateDVal(typeInt as ITypeBasic);
            bool res = core.TypeFinder.IsTypeInt(dv);
            res = core.TypeFinder.IsTypeString(dv);
            IType type = core.TypeFinder.GetTypeOfValue(dv);

            ValueString dvString = core.DataBuilder.CreateDValString("bonjour");
            type = core.TypeFinder.GetTypeOfValue(dvString);
        }

        //---------------------------------------------------------------------
        // Create dataValue only based on defined type
        static void CantCreateDataValueOnUndefinedType()
        {
            BluyelCore core = new BluyelCore();
            IType typeInt = core.TypeBuilder.DefineTypeInt();

            IType type;

            // failed
            type = core.TypeFinder.GetTypeBool();
            ValueString dvString = core.DataBuilder.CreateDValString("bonjour");
            type = core.TypeFinder.GetTypeOfValue(dvString);
        }


        //---------------------------------------------------------------------
        /// <summary>
        /// Create var and const (data named) of type Basic.
        /// </summary>
        static void CreateVar_TypeBasic()
        {
            BluyelCore core = new BluyelCore();
            IType typeInt = core.TypeBuilder.DefineTypeInt();
            IType typeDouble = core.TypeBuilder.DefineTypeDouble();
            IType typeString = core.TypeBuilder.DefineTypeString();
            IType typeBool = core.TypeBuilder.DefineTypeBool();

            // int a = 12
            IDBasic dataA = core.DataBuilder.CreateVarBasic("a", core.TypeFinder.GetTypeInt());

            // set the value 12 to the var a
            ValueInt dvInt12 = core.DataBuilder.CreateDValInt(12);
            core.DataBuilder.SetDVal(dataA, dvInt12);

            // create var, int a=10, bool b=true
            DInt varA = core.DataBuilder.CreateVarInt("a", 10);
            DBool varB = core.DataBuilder.CreateVarBool("b", true);

            // now, a= 15
            core.DataBuilder.SetVal(varA, 15);

            // rem: creer 2 var de meme nom va fonctionner alors qu'il ne faudrait pas: c'est normal, pas de mgr/liste!

            // create a list to save global var and const (a space of varConst)
            ListData listVar = core.DataBuilder.CreateListData(TypeDef.ListVarDataName);
            listVar.Add(varA);
            listVar.Add(varB);

            // failed, already added
            bool res= listVar.Add(varB);

            // Find a data named, a var, a const
            IDataNamed data= listVar.FindDataByName("a");

            // get all var by a type (all int var),...
            List<IDataNamed> listVarInt= listVar.ListData.ToList().FindAll(v => v.Type.Id.IdAreEquals(TypeDef.TypeIntId));

        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create const (data named) of type Basic.
        /// </summary>
        static void CreateConst_TypeBasic()
        {
            BluyelCore core = new BluyelCore();
            core.TypeBuilder.DefineAllTypes();

            // create const: int a=10, bool b=true
            DInt constA = core.DataBuilder.CreateConstInt("a", 10);
            DBool constB = core.DataBuilder.CreateConstBool("b", true);
            DString constC = core.DataBuilder.CreateConstString("c", "hello");
            DDouble constD = core.DataBuilder.CreateConstDouble("d", 34.56);

            // try to modifiy a const: failed
            bool res= core.DataBuilder.SetVal(constA, 12);

        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create a data named : structure (anonymous type), has fields (dataNamed).
        /// IDataNStruct
        /// </summary>
        static void CreateVarDStruct()
        {
            BluyelCore core = new BluyelCore();
            IType typeInt = core.TypeBuilder.DefineTypeInt();
            IType typeDouble = core.TypeBuilder.DefineTypeDouble();
            IType typeString = core.TypeBuilder.DefineTypeString();
            IType typeBool = core.TypeBuilder.DefineTypeBool();

            // create the type DataNStruct, to be possible to create DataNStruct instance.
            ITypeStruct typeStruct = core.TypeBuilder.DefineTypeStruct();

            // Create a var data structure, with some data basic type  
            // struct st
            //   int a= 12
            //   bool b
            //   string s="hello"
            // end
            IDStruct dataSt = core.DataBuilder.CreateVarStruct("st");

            // add members (dataNamed): a
            DInt varSt_a = core.DataBuilder.AddVarStructMemberInt(dataSt, "a");

            string s = varSt_a.ToString();

            // set a value to a member: st.a= 12
            core.DataBuilder.SetVal(varSt_a, 12);

            // add members (dataNamed): b
            IDBasic varSt_b = core.DataBuilder.AddVarStructMemberBool(dataSt, "b");

            // add members (dataNamed): c
            IDBasic varSt_c = core.DataBuilder.AddVarStructMemberString(dataSt, "c", "hello");

            // remove a member
            bool res= core.DataBuilder.RemoveVarStructMember(dataSt, "b");

            // find a data member
            IDataNamed dFind = dataSt.FindMember("a");

            // create a var list, and save the dataStruct
            ListData listVar = core.DataBuilder.CreateListData(TypeDef.ListVarDataName);
            listVar.Add(dataSt);

            listVar.Remove("st");
            // TODO:

        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create const (data named) of data struct.
        /// </summary>
        static void CreateConst_DStruct()
        {
            BluyelCore core = new BluyelCore();
            core.TypeBuilder.DefineAllTypes();

            // Create a var data structure, with some data basic type  
            // struct st
            //   const int a= 12
            //   const string s="hello"
            // end
            IDStruct dataSt = core.DataBuilder.CreateVarStruct("st");

            // add members (dataNamed): b
            DInt varSt_a = core.DataBuilder.AddConstStructMemberInt(dataSt, "a", 12);

            // add members (dataNamed): c
            DString varSt_b = core.DataBuilder.AddConstStructMemberString(dataSt, "c", "hello");

        }

        //---------------------------------------------------------------------
        // realiste de creer une const data struct?? ou juste sur les membres. 
        // faire que sur les members pour commencer, const DStruct sera fait +tard si demande
        //
        // IDStruct dataSt = core.DataBuilder.CreateConstStruct("st");

        
        //---------------------------------------------------------------------
        /// <summary>
        /// create LOV type (item as string, DataValueString)
        /// create LOV data based on a LOVtype (item as string, DataValueString)
        /// </summary>
        static void CreateLOV_String()
        {
            BluyelCore core = new BluyelCore();
            IType typeInt = core.TypeBuilder.DefineTypeInt();
            IType typeDouble = core.TypeBuilder.DefineTypeDouble();
            IType typeString = core.TypeBuilder.DefineTypeString();

            // create typeLOV, values are typeof string
            ITypeEnumString typeLOVWeekDay = core.TypeBuilder.CreateTypeEnumString("typeLOVWeekDay");

            // can't create
            ITypeEnumString typeLOV2 = core.TypeBuilder.CreateTypeEnumString("typeLOVWeekDay");

            ITypeEnum typeLOVToRemove = core.TypeBuilder.CreateTypeEnumString("typeLOVRemove");
            // remove a LOV type
            bool res= core.TypeBuilder.RemoveTypeEnumByName("typeLOVRemove");

            // add value to the LOV
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "noDay");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Monday");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Thursday");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Wenesday");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Blabla");

            // remove a value from a LOV
            res = core.TypeBuilder.RemoveEnumValue(typeLOVWeekDay, "noDay");
            res = core.TypeBuilder.RemoveEnumValueByPos(typeLOVWeekDay, 3);

            if (core.TypeFinder.TypeEnumContains(typeLOVWeekDay, "Monday"))
                Console.WriteLine("Yes, the typeLOV contains the item: Monday");

            // create data typeof LOV
            // the default mode is: Single(Single, Many), the default selected value is the first one (or none?).
            IDEnumString lovWeekDay = core.DataBuilder.CreateVarEnumString(typeLOVWeekDay, "MyLov");

            // no selected value, is null
            IValue dvSelect = lovWeekDay.SelectedVal;

            // select a value in the LOV
            res = core.DataBuilder.SelectEnumStringVal(lovWeekDay, "Monday");

            // selected value is 'Monday'
            dvSelect = lovWeekDay.SelectedVal;

            // set the current value of the LOV : wrong value
            core.DataBuilder.SelectEnumValueAt(lovWeekDay, -1);

            // selected value is the same
            dvSelect = lovWeekDay.SelectedVal;

            // set the current value of the LOV ( -1 to unselect)
            core.DataBuilder.SelectEnumValueAt(lovWeekDay, 2);
            // selected value is 'Wenesday'
            dvSelect = lovWeekDay.SelectedVal;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create LOV type (item as string, DataValueString)
        /// create LOV data based on a LOVtype (item as string, DataValueString)
        /// </summary>
        static void CreateLOV_String_SelectMode_Many()
        {
            BluyelCore core = new BluyelCore();
            core.TypeBuilder.DefineAllTypes();

            // create typeLOV, values are typeof string
            ITypeEnumString typeLOV_A= core.TypeBuilder.CreateTypeEnumString("typeLOV_A");
            // get the default selection mode
            TypeEnumSelectMode selectMode_A = typeLOV_A.SelectMode;

            // create typeLOV, values are typeof string
            ITypeEnumString typeLOVWeekDay = core.TypeBuilder.CreateTypeEnumString("typeLOVWeekDay", TypeEnumSelectMode.Many);
            // get the default selection mode
            TypeEnumSelectMode selectMode = typeLOVWeekDay.SelectMode;

            // add value to the LOV
            bool res;
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Monday");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Thursday");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Wenesday");

            // create data typeof LOV
            // the default mode is: Single(Single, Many), the default selected value is the first one (or none?).
            IDEnumString lovWeekDay = core.DataBuilder.CreateVarEnumString(typeLOVWeekDay, "MyLov");


            // TODO: select many values
            core.DataBuilder.SelectEnumValueAt(lovWeekDay, 2);
            res = core.DataBuilder.SelectEnumStringVal(lovWeekDay, "Thursday");

            // get list of selected values
            IEnumerable<ValueString> listSelectedVal = lovWeekDay.ListSelectedVal;

            core.DataBuilder.ClearEnumSelection(lovWeekDay);


            // TODO:  creer TypeLOV selectMode= SetInVar  + data LOV Many

        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create LOV type (item as string, DataValueString)
        /// create LOV data based on a LOVtype (item as string, DataValueString)
        /// </summary>
        static void CreateLOV_String_SelectMode_SetInVar_Data_Single()
        {
            BluyelCore core = new BluyelCore();
            core.TypeBuilder.DefineAllTypes();

            // create typeLOV, values are typeof string
            ITypeEnumString typeLOV_A = core.TypeBuilder.CreateTypeEnumString("typeLOV_A");
            // get the default selection mode
            TypeEnumSelectMode selectMode_A = typeLOV_A.SelectMode;

            // create typeLOV, values are typeof string
            ITypeEnumString typeLOVWeekDay = core.TypeBuilder.CreateTypeEnumString("typeLOVWeekDay", TypeEnumSelectMode.SetInVar);
            // get the default selection mode
            TypeEnumSelectMode selectMode = typeLOVWeekDay.SelectMode;

            // add value to the LOV
            bool res;
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Monday");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Thursday");
            res = core.TypeBuilder.AddEnumValue(typeLOVWeekDay, "Wenesday");

            // create data typeof LOV
            IDEnumString lovWeekDay = core.DataBuilder.CreateVarEnumString(typeLOVWeekDay, DEnumSelectMode.Single, "MyLov");

            // select one value 
            // TODO:
            //ici();
        }

        //---------------------------------------------------------------------
        static void CreateLOV_String_SelectMode_SetInVar_Data_Many()
        {
            // TODO:
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create the "sugar" method: create all types with a single method.
        /// </summary>
        static void CreateTypeWithOneCoreMethod()
        {
            BluyelCore core = new BluyelCore();

            // replace all these calls by a single one:
            //core.TypeBuilder.CreateTypeInt();
            //core.TypeBuilder.CreateTypeDouble();
            //core.TypeBuilder.CreateTypeString();
            //core.TypeBuilder.CreateTypeBool();

            core.TypeBuilder.DefineAllTypes();

        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create the type Physical Quantity Length, configure
        /// and define some data values.
        /// </summary>
        static void CreateTypePhyLengthAndDVal()
        {
            BluyelCore core = new BluyelCore();

            // create the type PhysQty Length, default prefix is Metre
            TypePhyLength typeLength = core.TypeBuilder.DefineTypePhyLength();

            // configure phys qty system, define some default parameters
            // TODO:  set the default prefix?  set the default value?

            // create a length data value: 6 m (6 mètres)
            // DValPhysQtyLength, DValPQLength, DV_PQ_Length
            ValuePhyLength dvLength6m = core.ValueBuilder.CreateValuePhyLength();

            // set the value and the prefix/multiple
            bool res = core.ValueBuilder.SetVal(dvLength6m, 6, TypePhyLengthPrefix.Metre);

            // create a length data value: 453 cm (453 centimetre)
            ValuePhyLength dvLength453cm = core.ValueBuilder.CreateValuePhyLength(453, TypePhyLengthPrefix.Centimetre);

            // convert the dv in cm: 6m= 600cm 
            ValuePhyLength dvLength6mTocm = core.ValueConverter.PhyConverter.ConvertTo(dvLength6m, TypePhyLengthPrefix.Centimetre);

            // convert the dv in km: 6m= 0,006km 
            ValuePhyLength dvLength6mTokm = core.ValueConverter.PhyConverter.ConvertTo(dvLength6m, TypePhyLengthPrefix.Kilometre);

            // is 6m > 453cm ? =true
            res = core.ValueConverter.PhyConverter.IsGreaterThan(dvLength6m, dvLength453cm);
            // is 6m < 453cm ? = false
            res = core.ValueConverter.PhyConverter.IsLessThan(dvLength6m, dvLength453cm);

            // is 6m == 600cm ? = true
            res = core.ValueConverter.PhyConverter.AreEquals(dvLength6m, dvLength6mTocm);
        }

        //---------------------------------------------------------------------
        static void CreatePhyLengthYardAndConvert()
        {
            BluyelCore core = new BluyelCore();

            // create the type PhysQty Length, default prefix is Metre
            TypePhyLength typeLength = core.TypeBuilder.DefineTypePhyLength();

            // create a length data value: 1 m
            ValuePhyLength dvLengthOneMetre = core.ValueBuilder.CreateValuePhyLength(1, TypePhyLengthPrefix.Metre);

            // create a length data value: 1 yard 
            ValuePhyLength dvLengthOneYard = core.ValueBuilder.CreateValuePhyLength(1, TypePhyLengthPrefix.Yard);

            // convert 1 yard -> m  => 1 yard= 0.9144 metre
            ValuePhyLength dvLength1yard_09144m = core.ValueConverter.PhyConverter.ConvertTo(dvLengthOneYard, TypePhyLengthPrefix.Metre);

            // convert 1 m -> yard  => 1 m = 1,0936... yard
            ValuePhyLength dvLength1m_1_0936XXYard = core.ValueConverter.PhyConverter.ConvertTo(dvLengthOneMetre, TypePhyLengthPrefix.Yard);

            // convert 1 yard -> yard  = 1 yard!
            ValuePhyLength dvLength1YardRes = core.ValueConverter.PhyConverter.ConvertTo(dvLengthOneYard, TypePhyLengthPrefix.Yard);
        }

        //---------------------------------------------------------------------
        static void CreatePhyLengthInchAndConvert()
        {
            BluyelCore core = new BluyelCore();

            // create the type PhysQty Length, default prefix is Metre
            TypePhyLength typeLength = core.TypeBuilder.DefineTypePhyLength();

            // create a length data value: 1 m
            ValuePhyLength dvLengthOneMetre = core.ValueBuilder.CreateValuePhyLength(1, TypePhyLengthPrefix.Metre);

            // create a length data value: 1 inch 
            ValuePhyLength dvLengthOneInch = core.ValueBuilder.CreateValuePhyLength(1, TypePhyLengthPrefix.Inch);

            // convert 1 inch -> m  => 1 inch= 0.0254 metre
            ValuePhyLength dvLength1yard_0_0254m = core.ValueConverter.PhyConverter.ConvertTo(dvLengthOneInch, TypePhyLengthPrefix.Metre);

        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create var of type physical qty.
        /// </summary>
        static void CreateVarPhyLength()
        {
            BluyelCore core = new BluyelCore();

            // create the type PhysQty Length, default prefix is Metre
            TypePhyLength typeLength = core.TypeBuilder.DefineTypePhyLength();
            
            // create the var a: PhyLength a=12m
            IDPhyLength varA= core.DataBuilder.CreateVarPhyLength("a");
            core.DataBuilder.SetVal(varA, 12, TypePhyLengthPrefix.Metre);

            // create the var b: PhyLength b=27cm
            IDPhyLength varB = core.DataBuilder.CreateVarPhyLength("a", 27, TypePhyLengthPrefix.Centimetre);

        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Create constant of type physical qty.
        /// </summary>
        static void CreateConstPhyLength()
        {
            BluyelCore core = new BluyelCore();

            // create the type PhysQty Length, default prefix is Metre
            TypePhyLength typeLength = core.TypeBuilder.DefineTypePhyLength();

            // create the var a: PhyLength a=27cm
            IDPhyLength constA = core.DataBuilder.CreateConstPhyLength("a", 27, TypePhyLengthPrefix.Centimetre);

            // try to modify the const
            core.DataBuilder.SetVal(constA, 12, TypePhyLengthPrefix.Metre);
            Console.WriteLine("type=" + constA.Type);
        }


        //---------------------------------------------------------------------
        /// <summary>
        /// Create var data named struct typeof physical qty.
        /// </summary>
        static void CreateVarDStructWithMembersPhyLength()
        {
            BluyelCore core = new BluyelCore();

            // create all std types
            core.TypeBuilder.DefineAllTypes();

            // Create a var data structure, with some data basic type  
            // struct st
            //   int a= 12
            //   Length l
            //   Length h=37 Metre
            // end
            IDStruct dataSt = core.DataBuilder.CreateVarStruct("st");

            // add a member: int a= 12
            IDBasic varSt_a = core.DataBuilder.AddVarStructMemberInt(dataSt, "a", 12);

            IDPhy varSt_l = core.DataBuilder.AddVarStructMemberPhyLength(dataSt, "l");

            // add a member: Length h= 37 Metre
            IDPhy varSt_h = core.DataBuilder.AddVarStructMemberPhyLength(dataSt, "h", 37, TypePhyLengthPrefix.Metre);

            IDPhy constSt_p = core.DataBuilder.AddConstStructMemberPhyLength(dataSt, "h", 37, TypePhyLengthPrefix.Metre);

            // find the data member l
            IDataNamed dFind = dataSt.FindMember("l");
        }

        //---------------------------------------------------------------------
        // TODO-ROADMAP:


        //----
        // Create an open Data LOV.
        // Select a value from the LOV or set it (like an combobox).


        //----
        // create type container: list, of DataValue
        // que type (list)

        //----
        // create type container: list, of DataValueString
        // ITypeSet ou ITypeContainer <- ITypeList

        //----
        // create a data named typeof container: List  of DVString

        //----
        // create special type (used as function return for example)
        //core.CreateTypeFolder();
        //core.CreateTypeVoid();

        // create type class (donnée simple) et instance
        // TypeClass, by user


        //---------------------------------------------------------------------
        static void Dev()
        {
            BluyelCore core = new BluyelCore();

        }

        //---------------------------------------------------------------------
        static void Tests()
        {
            CoreVarDLOVStringTest test = new CoreVarDLOVStringTest();

            test.CreateDLOVString_SelectMode_Many_SelectManyVal();


        }
        //---------------------------------------------------------------------
        static void Main(string[] args)
        {
            //CreateBasicType();
            //CreateBasicTypeSetName();
            //CreateBasicTypePutInListType();

            //CreateDataValueBasicType();

            //CantCreateDataValueOnUndefinedType();

            //CreateVar_TypeBasic();
            //CreateConst_TypeBasic();

            //CreateDataNamed_Struct();

            //CreateLOV_String();
            //CreateLOV_String_SelectMode_Many();
            CreateLOV_String_SelectMode_SetInVar_Data_Single();

            //CreateTypeWithOneCoreMethod();

            //CreateTypePhyLengthAndDVal();

            //CreatePhyLengthYardAndConvert();

            //CreatePhyLengthInchAndConvert();

            //CreateVarPhyLength();
            //CreateConstPhyLength();
            //CreateVarDStructWithMembersPhyLength();

            Tests();

        }

    }
}
